#include <stdio.h>
#include "Types.h"
#include "HVACControl.h"
#include "hvac.h"
#include "eeprom.h"
#include "testing.h"
#include "ZSysgen.h"
#include "ZTypes.h"
#include "ZThread.h"
#include "ZTimer.h"

#ifdef RUNNING_STATE_TRANS_TESTS

void executeNewState(int i, hvac_mode_t HVACMode, fan_mode_t fanMode, heater_t heaterType, temp_t setTemp);
void printHeader(int i);
void printSettings(hvac_mode_t HVACMode, fan_mode_t fanMode, heater_t heaterType, temp_t setTemp);
void printFooter();
void printCurState();
void checkResults();

//Timer Variables
extern TICK_t ticksPerSecond;
void testingTimerFunction();
RZK_TIMERHANDLE_t testingTimerHandle;
TICK_t testingTimerInitialDelay;
TICK_t testingTimerPeriod;


extern hvac_state_t curHVACState;
extern fan_state_t curFanState;


#define NUM_HVAC_MODES 		3
#define NUM_FAN_MODES 		2
#define NUM_HEATER_TYPES	2

int numTotalStates = NUM_HVAC_MODES * NUM_FAN_MODES * NUM_HEATER_TYPES * 2;
state_t states[NUM_HVAC_MODES * NUM_FAN_MODES * NUM_HEATER_TYPES * 2];

int outerState = 0;
int innerState = 0;
int testNum = 1;

hvac_mode_t HVACMode;
fan_mode_t fanMode;
heater_t heaterType;
temp_t setTemp;

/*
 * This is designed to run through every possible critical HVAC state change
 * in every possible direction.  The settings are changed and saved to flash
 * for the HVAC control thread to adjust accordingly
 *
 * Note: This is based off the assumption that:
 *			1) The polling interval for the HVAC thread is never changed from the default
 *			2) This timer is created a few seconds after the HVAC thread so that is can
 *			   save new settings in between each adjustHVAC poll
 * Params:
 *		none
 *
 * Returns:
 *		none
 */
error_t initTesting()
{
	int i, j, k;
	int index = 0;

    //These are the setTemps that will activate each HVAC mode to be "On"
    // The array lines up with the values of the HVACModes
    int onTemps[] = { 75, 90, 60 };
    int offTemps[] = { 75, 60, 90};

	// Generate all states
	for (i = 0; i < NUM_HVAC_MODES; i++)
    {
        for (j = 0; j < NUM_FAN_MODES; j++)
        {
            for (k = 0; k < NUM_HEATER_TYPES; k++)
            {
				state_t sOn;
				state_t sOff;
				sOn.HVACMode = i;
				sOn.fanMode = j;
				sOn.heater = k;
				sOn.setTemp = onTemps[i];
				states[index] = sOn;
				index++;

				sOff.HVACMode = i;
				sOff.fanMode = j;
				sOff.heater = k;
				sOff.setTemp = offTemps[i];
				states[index] = sOff;
				index++;
			}
		}
	}

	printf("Creating testing timer...\n");
	
	testingTimerPeriod = ticksPerSecond * DEFAULT_POLLING_INTERVAL;
	testingTimerInitialDelay = (DEFAULT_POLLING_INTERVAL / 2) * ticksPerSecond - 10;
	testingTimerHandle = RZKCreateTimer(NULL, testingTimerFunction, testingTimerInitialDelay, testingTimerPeriod);	

	if(RZKEnableTimer(testingTimerHandle) != RZKERR_SUCCESS)
	{
		printf("Error creating testing timer\n");
		return GENERAL_ERROR;
	}
	else
	{
		printf("Testing timer created successfully!\n");
		return SUCCESS;
	}

}


void testingTimerFunction()
{
	/* Trying to follow this format
	// Run through every possible transition
	for (i = 0; i < numTotalStates; i++)
    {
        for (j = 0; j < numTotalStates; j++)
        {
            if (j != i)
            {
                HVACMode = states[j].HVACMode;
				fanMode = states[j].fanMode;
				heaterType = states[j].heater;
				setTemp = states[j].setTemp;
				executeNewState(testNum, HVACMode, fanMode, heaterType, setTemp);
				testNum++;
            }
        }
    }
	*/
	if(testNum != 1)
	{
		checkResults();
	}

	if(outerState == innerState)
	{
		if(innerState == numTotalStates - 1)
		{
			//This is the last inner state
			innerState = 0;
			if(outerState < numTotalStates - 1)
			{
				innerState++;
			}
			else
			{
				RZKDisableTimer(testingTimerHandle);
				return;
			}
		}
		else
		{
			innerState++;
		}
	}
	else if(innerState == numTotalStates)
	{
		innerState = 0;
		outerState++;
	}
	
	HVACMode = states[innerState].HVACMode;
	fanMode = states[innerState].fanMode;
	heaterType = states[innerState].heater;
	setTemp = states[innerState].setTemp;
	executeNewState(testNum, HVACMode, fanMode, heaterType, setTemp);

	innerState++;
	testNum++;
}

		
/*
 *	This private function saves the passed in settings to flash for use by the adjustHVAC
 *  It also prints out appropriate header, footers, and useful testing information
 *
 * Params:
 *		i - The test number to print
 *		HVACMode
 *		fanMode
 *		heaterType
 *		setTemp
 *
 * Returns:
 *		none
 */
void executeNewState(int i, hvac_mode_t HVACMode, fan_mode_t fanMode, heater_t heaterType, temp_t setTemp)
{
	eeprom_settings_t allSettings;
	hvac_settings_t *hvacSettings;
	eepromGetSettings(&allSettings);
	hvacSettings = &allSettings.hvacSettings;

	// Print useful information before saving new settings
	printHeader(i);
    printf("Starting ");
    printCurState();
	printf("\n");

	// Set the settings
	hvacSettings->setHVACMode = HVACMode;
	hvacSettings->setFanMode = fanMode;
    hvacSettings->myHeaterType = heaterType;
    hvacSettings->setTemp = setTemp;
	// Print what settings we are testing
	printSettings(HVACMode, fanMode, heaterType, setTemp);    

	// Save them
	eepromSaveSettings(&allSettings);
}

void printHeader(int i)
{
	printf("************** Test %d **************\n", i);
}

void printFooter()
{
	printf("************************************\n");
}

void printSettings(hvac_mode_t HVACMode, fan_mode_t fanMode, heater_t heaterType, temp_t setTemp)
{
	printf("Setting:");
	if(HVACMode == OFF)
	{
		printf("OFF");
	}
	else if(HVACMode == HEAT)
	{
		printf("HEAT");
	}
	else if(HVACMode == AC)
	{
		printf("AC");
	}

	if(fanMode == FAN_AUTO)
	{
		printf("\tFAN_AUTO");
	}
	else if(fanMode == FAN_ON)
	{
		printf("\tFAN_ON");
	}

	if(heaterType == GAS)
	{
		printf("\tGAS");
	}
	else if(heaterType == ELECTRIC)
	{
		printf("\tELECTRIC");
	}

	printf("\t%d\n\n", setTemp);
}


void printCurState()
{
	printf("HVAC State:\n");

	if(curHVACState == HEATING)
	{
		printf("\tHEATING\n");
	}
	else if(curHVACState == COOLING)
	{
		printf("\tCOOLING\n");
	}
	else if(curHVACState == IDLE)
	{
		printf("\tIDLE\n");
	}

	if(curFanState == FAN_AUTO)
	{
		printf("\tFAN_IDLE\n");
	}
	else if(curFanState == FAN_ON)
	{
		printf("\tFAN_RUNNING\n");
	}
	
}


void checkResults()
{
	// Print final states
    printf("\nFinal ");
    printCurState();

	// Did we pass?
	if(HVACMode == HEAT)
	{
		if(setTemp > 80)
		{
			// It should be heating
			if(curHVACState == HEATING)
			{
				if(heaterType == GAS)
				{
					if(fanMode == FAN_AUTO)
					{
						if(curFanState == FAN_IDLE)
						{
							printf("Success!\n");
						}
						else
						{
							printf("!!!!!!!! Failure !!!!!!!!!!\n");
						}
					}
					else if(fanMode == FAN_ON && curFanState == FAN_RUNNING)
					{
						printf("Success!\n");
					}
					else
					{
						printf("!!!!!!!! Failure !!!!!!!!!!\n");
					}
				}
				else if(heaterType == ELECTRIC)
				{
					if(curFanState == FAN_RUNNING)
					{
						printf("Success!\n");
					}
					else
					{
						printf("!!!!!!!! Failure !!!!!!!!!!\n");
					}
				}
			}
			else
			{
				printf("!!!!!!!! Failure !!!!!!!!!!\n");
			}
		}
		else
		{
			//The heater should be off
			if(curHVACState == IDLE)
			{
				if(fanMode == FAN_AUTO && curFanState == FAN_IDLE)
				{
					printf("Success!\n");
				}
				else if(fanMode == FAN_ON && curFanState == FAN_RUNNING)
				{
					printf("Success!\n");
				}
				else
				{
					printf("!!!!!!!! Failure !!!!!!!!!!\n");
				}
			}
		}
	}
	else if(HVACMode == AC)
	{
		if(setTemp < 70)
		{
			// AC should be on
			if(curHVACState == COOLING)
			{
				if(curFanState == FAN_RUNNING)
				{
					printf("Success!\n");
				}
				else
				{
					printf("!!!!!!!! Failure !!!!!!!!!!\n");
				}
			}
			else
			{
				printf("!!!!!!!! Failure !!!!!!!!!!\n");
			}
		}
		else
		{
			// AC should be off
			if(curHVACState == IDLE)
			{
				// These checks assume no delayed fan shutoff for the AC!
				if(fanMode == FAN_AUTO && curFanState == FAN_IDLE)
				{
					printf("Success!\n");
				}
				else if(fanMode == FAN_ON && curFanState == FAN_RUNNING)
				{
					printf("Success!\n");
				}
				else
				{
					printf("!!!!!!!! Failure !!!!!!!!!!\n");
				}
			}
			else
			{
				printf("!!!!!!!! Failure !!!!!!!!!!\n");
			}
		}
	}
	else if(HVACMode == OFF)
	{
		if(fanMode == FAN_AUTO && curFanState == FAN_IDLE)
		{
			printf("Success!\n");
		}
		else if(fanMode == FAN_ON && curFanState == FAN_RUNNING)
		{
			printf("Success!\n");
		}
		else
		{
			printf("!!!!!!!! Failure !!!!!!!!!!\n");
		}
	}

    printFooter();
}


#endif